package plus.exp;

import java.util.LinkedList;

import plus.Identifier;
import plus.Symbol;
import plus.Variable;
import plus.run.Emit;

public final class E_Ident extends Exp {
	Identifier id;
	public E_Ident(Identifier id) { this.id = id; }
	Exp call(LinkedList<Exp> es) { return new E_Call(id, es); }
	
	
	private Variable v;
	// TODO this is a poor test of variable initialization.
	@Override
	public void threadScope() {
		// If we get here, then it's a variable.
		Symbol<Variable> sv = id.asVar();
		if (null == sv) id.gripe("undefined variable");
		v = sv.definition; assert(v.type != null);
		// The following is all kinds of wrong:
		//if (!v.assigned) id.gripe("variable must be assigned before use");
		type = v.type;
	}
	@Override
	public void threadAssign() {
		Symbol<Variable> sv = id.asVar();
		if (null == sv) sv = id.addVar();
		v = sv.definition; assert(v.type != null);
		if (v.assigned && ! v.declared) id.gripe("undeclared variable updated");
		v.assigned = true;
		type = v.type;
	}
	@Override String impliedName() { return id.name; }
	@Override String aThis() { return "a variable"; }

	@Override
	public void compilePush() {
		Emit.staticPtr(v.depth);
		Emit.readStack(v.offset);
	}
	@Override
	public void compileAssign(Exp rhs) {
		rhs.compilePush();
		Emit.staticPtr(v.depth);
		Emit.writeStack(v.offset);
	}
}
